package io.geekidea.boot.salesslip.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import io.geekidea.boot.auth.util.LoginUtil;
import io.geekidea.boot.common.PageDto;
import io.geekidea.boot.framework.response.ApiResult;
import io.geekidea.boot.inventorychange.entity.StoreChange;
import io.geekidea.boot.inventorychange.service.StoreChangeService;
import io.geekidea.boot.materials.entity.Materials;
import io.geekidea.boot.materials.service.MaterialsService;
import io.geekidea.boot.outbound.dto.OutboundExcel;
import io.geekidea.boot.outbound.query.OutboundQuery;
import io.geekidea.boot.salesslip.dto.SalesslipDto;
import io.geekidea.boot.salesslip.dto.SalesslipExcel;
import io.geekidea.boot.salesslip.entity.Salesslip;
import io.geekidea.boot.salesslip.query.SalesslipQuery;
import io.geekidea.boot.salesslip.service.SalesslipService;
import io.geekidea.boot.store.entity.Store;
import io.geekidea.boot.store.service.StoreService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.ml.neuralnet.UpdateAction;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/salesslip")
@Tag(name="销售单管理")
public class SalesslipController {
    @Resource
    SalesslipService SalesslipService;
    @Resource
    private MaterialsService materialsService;
    @Resource
    private StoreChangeService storeChangeService;
    @Resource
    private StoreService storeService;

    @PostMapping("/searchPage")
    @Operation(summary = "搜索销售单",description = "按照多条件组合分页查询销售单数据列表")
    public ApiResult search(@RequestBody SalesslipQuery salesslipQuery){
        Page<Salesslip> page=new Page<>(salesslipQuery.getPage(),salesslipQuery.getSize());
        Page<Salesslip> pageDto=SalesslipService.getSalesslipPageList(page,salesslipQuery);
        PageDto<Salesslip> pageInfo=new PageDto<>(pageDto.getRecords(),pageDto.getTotal(),pageDto.getSize(),pageDto.getCurrent());
        return ApiResult.success(pageInfo);
    }



    @GetMapping("/get/{id}")
    @Operation(summary = "根据ID查询单条数据")
    public ApiResult getAreaById(@PathVariable(value = "id")Integer id){
        final  Salesslip salesslip =SalesslipService.getById(id);
        return ApiResult.success(salesslip);
    }

    @DeleteMapping("/romove/{id}")
    @Operation(summary = "逻辑删除销售单")
    public ApiResult removeArea(@PathVariable(value = "id")Integer id){
        SalesslipService.removeById(id);
        return ApiResult.success("删除销售单数据成功！");
    }

    @PostMapping("/add")
    @Operation(summary = "添加销售单")
    public ApiResult addSalesslip(@RequestBody SalesslipDto salesslipDto) throws Exception {
        salesslipDto.setOrderTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        salesslipDto.setCreatedTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        salesslipDto.setCreatorUser(LoginUtil.getUsername());
        salesslipDto.setCreatedBy(LoginUtil.getUsername());
        Salesslip salesslipEntity = new Salesslip();
        BeanUtil.copyProperties(salesslipDto,salesslipEntity);
        SalesslipService.save(salesslipEntity);
        //计算门店物料库存数据
        calculateInventory(salesslipDto.getMaterialDetails(),salesslipDto);
        return ApiResult.success("添加销售单数据成功！");
    }

    public void calculateInventory(String materialDetails,SalesslipDto salesslipDto) throws Exception {
        //解析物料json字符串转json
        JSONArray jsonArray = new JSONArray(materialDetails);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObj = jsonArray.getJSONObject(i);
            //物料名称
            String name = jsonObj.getObj("name").toString();
            if (!name.equals("")&&!name.equals(null)){
                //门店物料库id
                Integer wlId = Integer.parseInt(jsonObj.getObj("wlId").toString());
                //出库数量
                Integer xsNum =  Integer.parseInt(jsonObj.getObj("xsNum").toString());
                //总库存
                Integer totalStock =  Integer.parseInt(jsonObj.getObj("totalStock").toString());
                //门店安全库存数量
                Integer availableInventory =  Integer.parseInt(jsonObj.getObj("availableInventory").toString());
                //门店锁定全库存数量
                Integer lockInventory =  Integer.parseInt(jsonObj.getObj("lockInventory").toString());

                //修改库存数量
                Materials materialsEntity=new Materials();
                materialsEntity.setId(wlId);
                materialsEntity.setTotalStock(totalStock);
                //可用库存数量
                materialsEntity.setAvailableInventory(String.valueOf(availableInventory));
                //锁定库存数量
                materialsEntity.setLockInventory(String.valueOf(lockInventory));
                materialsService.updateById(materialsEntity);

                StoreChange storeChange = new StoreChange();
                storeChange.setWarehouseentrynumber(salesslipDto.getNumbers());
                storeChange.setMaterialcode(jsonObj.getObj("code").toString());
                storeChange.setMaterialsnmark(jsonObj.getObj("taxsh").toString());
                storeChange.setNameofmaterial(jsonObj.getObj("name").toString());
                storeChange.setMaterialswarehouse(jsonObj.getObj("warehouseName").toString());
                storeChange.setTypeofchange(salesslipDto.getType());
                storeChange.setChangebehavior("销售");
                storeChange.setQuantityofchange(String.valueOf(xsNum));
                storeChange.setQuantityinstock(String.valueOf(totalStock));
                storeChange.setAvailablestock(String.valueOf(availableInventory));
                storeChange.setLockininventory(String.valueOf(lockInventory));
                storeChange.setTimeofchange(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                storeChange.setCreatedTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                storeChange.setCreatedBy(LoginUtil.getUsername());
                storeChange.setAreanameFk(salesslipDto.getAreaId());
                storeChange.setStorenameFk(salesslipDto.getStoresId());
                storeChangeService.save(storeChange);
            }

        }
    }


    @GetMapping("/del/{id}")
    @Operation(summary = "物理删除",description = "根据id物理删除对应的列")
    public ApiResult del(@PathVariable Integer id){
        int count = SalesslipService.delById(id);
        if (count<0) {
            return ApiResult.success("删除失败");
        }
        return ApiResult.success("删除成功");

    }

    @PostMapping("/update")
    @Operation(summary = "修改销售单")
    public ApiResult update(@Validated(value = {UpdateAction.class})@RequestBody SalesslipDto salesslipDto) throws Exception {
        //因为修改前需要取消之前的锁定库存和可用库存  再进行修改操作
        //查询该订单明细信息
        final Salesslip salesslip=SalesslipService.getById(salesslipDto.getId());
        //解析物料json字符串转json
        JSONArray jsonArray = new JSONArray(salesslip.getMaterialDetails());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObj = jsonArray.getJSONObject(i);
            //物料名称
            String name = jsonObj.getObj("name").toString();
            if (!name.equals("")&&!name.equals(null)){
                //门店物料库id
                Integer wlId = Integer.parseInt(jsonObj.getObj("wlId").toString());
                //出库数量
                Integer xsNum =  Integer.parseInt(jsonObj.getObj("xsNum").toString());
                //总库存
                Integer totalStock =  Integer.parseInt(jsonObj.getObj("totalStock").toString());
                //门店可用库存数量
                Integer availableInventory =  Integer.parseInt(jsonObj.getObj("availableInventory").toString());
                //门店锁定全库存数量
                Integer lockInventory =  Integer.parseInt(jsonObj.getObj("lockInventory").toString());
                //计算门店可用库存数量 = 门店可用库存数量 + 出库数量
                Integer num =  availableInventory + xsNum;
                //计算新的锁定库存
                Integer newXsNum =  lockInventory - xsNum;
                //修改库存数量
                Materials materialsEntity=new Materials();
                materialsEntity.setId(wlId);
                materialsEntity.setAvailableInventory(String.valueOf(num));
                materialsEntity.setTotalStock(totalStock);
                //锁定库存数量
                materialsEntity.setLockInventory(String.valueOf(newXsNum));
                materialsService.updateById(materialsEntity);

                StoreChange storeChange = new StoreChange();
                storeChange.setWarehouseentrynumber(salesslipDto.getNumbers());
                storeChange.setMaterialcode(jsonObj.getObj("code").toString());
                storeChange.setMaterialsnmark(jsonObj.getObj("taxsh").toString());
                storeChange.setNameofmaterial(jsonObj.getObj("name").toString());
                storeChange.setMaterialswarehouse(jsonObj.getObj("warehouseName").toString());
                storeChange.setTypeofchange(salesslipDto.getType());
                storeChange.setChangebehavior("销售");
                storeChange.setQuantityofchange(String.valueOf(xsNum));
                storeChange.setQuantityinstock(String.valueOf(totalStock));
                storeChange.setAvailablestock(String.valueOf(num));
                storeChange.setLockininventory(String.valueOf(newXsNum));
                storeChange.setTimeofchange(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                storeChange.setCreatedTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                storeChange.setCreatedBy(LoginUtil.getUsername());
                storeChange.setAreanameFk(salesslipDto.getAreaId());
                storeChange.setStorenameFk(salesslipDto.getStoresId());
                storeChangeService.save(storeChange);


            }

        }
        salesslipDto.setUpdatedTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        salesslipDto.setUpdatedBy(LoginUtil.getUsername());
        Salesslip salesslipEntity = new Salesslip();
        BeanUtil.copyProperties(salesslipDto,salesslipEntity);
        SalesslipService.updateById(salesslipEntity);
        //修改完成后需要对修改后的物料库存数据更改
        //计算门店物料库存数据
        calculateInventory(salesslipDto.getMaterialDetails(),salesslipDto);
        return ApiResult.success("修改销售单数据成功！");
    }

    @PostMapping("/getNumbers/{storeCode}")
    @Operation(summary = "生成销售单号",description = "根据门店编号生成销售单号")
    public ApiResult getNumbers(@PathVariable String storeCode ){
        Store store = storeService.getById(storeCode);
        String code = generateOrderNumber(store.getCode());
        return ApiResult.success("生成销售单号成功",code);
    }

    public String generateOrderNumber(String storeCode) {
        LocalDateTime now = LocalDateTime.now();
        String formattedDate = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        long sequenceNumber = new Date().getTime();
        return "xs_" + storeCode + "_" + formattedDate + "_" + sequenceNumber;
    }


    @PostMapping("/updateStatus")
    @Operation(summary = "审核入库单状态")
    public ApiResult updateStatus(@RequestBody SalesslipDto salesslipDto) throws Exception {
        Salesslip salesslipEntity=new Salesslip();
        salesslipEntity.setId(salesslipDto.getId());
        salesslipEntity.setOrderTime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        salesslipEntity.setExamineUser(LoginUtil.getUsername());
        salesslipEntity.setStatus(salesslipDto.getStatus());
        salesslipEntity.setExamineContent(salesslipDto.getExamineContent());
        SalesslipService.updateById(salesslipEntity);
        //3:审核完成  需要单独操作
        if (salesslipDto.getStatus().equals("3")) {
            //查询该订单明细信息
            final Salesslip salesslip=SalesslipService.getById(salesslipDto.getId());
            //解析物料json字符串转json
            JSONArray jsonArray = new JSONArray(salesslip.getMaterialDetails());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObj = jsonArray.getJSONObject(i);
                //物料名称
                String name = jsonObj.getObj("name").toString();
                if (!name.equals("")&&!name.equals(null)){
                    //门店物料库id
                    Integer wlId = Integer.parseInt(jsonObj.getObj("wlId").toString());
                    //出库数量
                    Integer xsNum =  Integer.parseInt(jsonObj.getObj("xsNum").toString());
                    //总库存
                    Integer totalStock =  Integer.parseInt(jsonObj.getObj("totalStock").toString());
                    //门店锁定全库存数量
                    Integer lockInventory =  Integer.parseInt(jsonObj.getObj("lockInventory").toString());
                    //计算门店库存剩余数量 = 门店库存数量 - 出库数量
                    Integer num =  totalStock - xsNum;
                    //计新锁定库存剩余数量 = 门店锁定全库存数量 - 出库数量
                    Integer newNum =  lockInventory - xsNum;

                    //修改库存数量
                    Materials materialsEntity=new Materials();
                    materialsEntity.setId(wlId);
                    materialsEntity.setTotalStock(num);
                    materialsEntity.setLockInventory(String.valueOf(newNum));
                    materialsService.updateById(materialsEntity);

                }

            }
        }
        return ApiResult.success("审核成功！");
    }

    @PostMapping("/remove/{id}")
    @Operation(summary = "删除销售单",description = "逻辑删除")
    public ApiResult removeSalesslip(@PathVariable(value = "id") Integer id) {
        SalesslipService.removeById(id);
        return ApiResult.success("删除入库单数据成功!");
    }

    @PostMapping("/download")
    @Operation(tags = "Post",description = "筛选加全部导出文件")
    public void download(@RequestBody SalesslipQuery salesslipQuery, HttpServletResponse response){
        List<SalesslipExcel> list = SalesslipService.getDownloadList(salesslipQuery);
        OutputStream outputStream = null;
        try {
            response.setCharacterEncoding("UTF-8");
            String excelName = URLEncoder.encode("salesslipentry_"+ LocalDateTime.now(), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + excelName + ".xlsx");
            // 以字节流的形式输出响应正文
            outputStream = response.getOutputStream();
            try (ExcelWriter excelWriter = EasyExcel.write(outputStream, SalesslipExcel.class).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
                excelWriter.write(list,writeSheet);
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    }

}
